package com.benshou.bsoa.common.dto;

import com.benshou.bsoa.common.trace.TraceIdContext;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import org.springframework.http.HttpStatus;

/**
 * 响应对象结构
 *
 * @param <T> 数据类型
 */
@Setter
@Getter
public class ResponseVo<T> {

    /**
     * 成功时的响应码值
     */
    public static final String SUCCESS_CODE = String.valueOf(HttpStatus.OK.value());

    /**
     * 响应码
     */
    @NonNull
    private String code;

    /**
     * 响应消息
     */
    private String message;

    /**
     * 数据
     */
    private T data;

    /**
     * 追踪Id
     */
    private String traceId;

    /**
     * 时间戳
     */
    @NonNull
    private Long timestamp;

    public ResponseVo() {
        this.code = SUCCESS_CODE;
        this.message = "success";
        this.timestamp = System.currentTimeMillis();
    }

    public ResponseVo(T data) {
        this();
        this.data = data;
    }

    public ResponseVo(T data, String message) {
        this(data);
        this.message = message;
    }

    public static <T> ResponseVo<T> success() {
        return new ResponseVo<>();
    }

    public static <T> ResponseVo<T> success(T data) {
        return new ResponseVo<>(data);
    }

    public static <T> ResponseVo<T> fail(String message) {
        ResponseVo<T> responseVo = new ResponseVo<>();
        responseVo.code = String.valueOf(HttpStatus.INTERNAL_SERVER_ERROR.value());
        responseVo.message = message;
        return responseVo;
    }

    public static <T> ResponseVo<T> fail(String code, String message) {
        ResponseVo<T> responseVo = new ResponseVo<>();
        responseVo.code = code;
        responseVo.message = message;
        return responseVo;
    }

    public static <T> ResponseVo<T> fail(String code, T data, String message) {
        ResponseVo<T> responseVo = new ResponseVo<>(data, message);
        responseVo.code = code;
        return responseVo;
    }

    public String getTraceId() {
        this.traceId = TraceIdContext.getCurrentTraceId();
        return this.traceId;
    }

    public boolean isSuccess() {
        return SUCCESS_CODE.equals(this.code);
    }
}
